import gosu.Sample;
import gosu.SampleInstance;

import org.jruby.*;
import org.jruby.runtime.*;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.anno.JRubyMethod;
import static org.jruby.RubyNumeric.*;


public class SampleProxy extends RubyObject {
  private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
    public IRubyObject allocate(Ruby runtime, RubyClass klass) {
      return new SampleProxy(runtime, klass);
    }
  };

  private Sample _sample;

  private final Ruby _runtime;

  public static void createSampleClass(Ruby runtime) {
    RubyModule mGosu = runtime.getModule("Gosu");
    RubyClass cSample = mGosu.defineClassUnder("Sample", runtime.getObject(), ALLOCATOR);

    cSample.defineAnnotatedMethods(SampleProxy.class);
  }


  public SampleProxy(Ruby runtime, RubyClass type) {
    super(runtime, type);
    _runtime = runtime;
  }


  public Sample getSample() { return _sample; }


  @JRubyMethod(name = "initialize",
               required = 2,
               visibility = Visibility.PRIVATE)
  public IRubyObject initialize(IRubyObject window, IRubyObject filename) {
    try {
      _sample = new Sample(((WindowProxy) window).getWindow(), ((RubyString) filename).toString());
    } catch (RuntimeException e) {
      throw _runtime.newRuntimeError(e.toString());
    }
    return this;
  }


  @JRubyMethod(name = "play",
               required = 0,
               optional = 2)
  public IRubyObject play(IRubyObject[] args) {
    SampleInstance si = null;

    switch (args.length) {
      case 0:
        si = _sample.play();
        break;
      case 1:
        si = _sample.play((float) num2dbl(args[0]));
        break;
      case 2:
        si = _sample.play((float) num2dbl(args[0]), (float) num2dbl(args[1]));
        break;
    }

    SampleInstanceProxy proxy = (SampleInstanceProxy) _runtime.getModule("Gosu").getClass("SampleInstance").allocate();
    proxy.setSampleInstance(si);
    return proxy;
  }


  @JRubyMethod(name = "play_pan",
               required = 1,
               optional = 2)
  public IRubyObject playPan(IRubyObject[] args) {
    SampleInstance si = null;

    switch (args.length) {
      case 1:
        si = _sample.playPan((float) num2dbl(args[0]));
        break;
      case 2:
        si = _sample.playPan((float) num2dbl(args[0]), (float) num2dbl(args[1]));
        break;
      case 3:
        si = _sample.playPan((float) num2dbl(args[0]), (float) num2dbl(args[1]), (float) num2dbl(args[2]));
        break;
    }

    SampleInstanceProxy proxy = (SampleInstanceProxy) _runtime.getModule("Gosu").getClass("SampleInstance").allocate();
    proxy.setSampleInstance(si);
    return proxy;
  }
}
